首发于Unity3D渲染
Unity SRP Batcher的工作原理

Unity SRP Batcher的工作原理

抓手

根据我的理解总结,SRP Batcher就是

1、把调用draw call前,一大堆CPU的设置工作给一口气处理了,增加了效率。

2、把材质的属性数据直接永久放入到显卡的CBUFFER里,那只要数据不变,CPU就可以

不需要把这些数据重新做设置工作。节省了CPU调用,增加了效率。

3、用专用的代码将引擎的属性(比如objects transform)直接放入到GPU显存,这个专用的代码是不是更快更强呢,

官方是这样么说的,用的词语是quickly,就是快。

4、SRP Batcher并没有减少drawcalls,而仅仅是提高了效率。相当于一个人减肥了,减去了多余的脂肪和水分,但是器官结构啥的一个没少。总之就是有用。

具体的解释

SRP Batcher定义:

SRP Batcher是一个渲染循环(loop),可在有很多使用相同的shader Variant的材质 的场景中,加速你的CPU渲染。

注意它的定义,也就是用的同一个shader,但是不同的材质,也能加速。

如果想使用SRP Batcher,必须符合以下任意一个管线:

1、URP管线(The Universal Render Pipeline)

2、HDRP管线(The High Definition Render Pipeline)

3、一个自定义的SRP(也就是自己写的SRP,手打牛肉丸)。

SRP Batcher的工作原理

SRP Batcher诞生的原因:

在一个Drawcall被一个新的material使用的时候,有很多工作要做。

所以如果场景有越多的materials,就会有越多的CPU必须使用去设置GPU 数据。

传统的方法是减少DrawCalls的数量去优化CPU渲染性能。

因为Unity必须在调用drawcall前设置很多东西。

并且真正的CPU消耗来自那些设置工作,而不是GPU drawcall本身。

Drawcall只是一些Unity向GPU command buffer发送的bytes。


SRP Batcher 通过批处理(batching)一系列绑定(Bind)和绘制(Draw)GPU 命令,来减少DrawCalls之间的GPU 设置(工作量)。也就是之前一堆绑定和绘制的GPU命令,老子一口气给它处理完。不需要一步步设置。


上面的图是我翻译的,可能有些不好理解,但是左右图比较看看的话,右图的工作量确实大大减少了,

毕竟从6个设置步骤减少成了2个。

为了让你的渲染达到最大的性能,这些批处理必须尽可能大。

为了达到这样的效果,你可以使用尽量多的同一个shader,但不同的材质,但是尽量少的shader变体。


SRP Batcher 是一个低级渲染循环,它使得Material 数据长久在GPU内存里。

如果Material内容不变,SRP Batcher就不需要设置并上传buffer到GPU里。

相反( 如果Material内容有变),SRP Batcher 使用专用的代码路径去快速更新Unity Engine属性到一个大型的GPU bufer里。如下:

所有Materials 有长久的CBUFFERs在GPU 显存里,并准备拿去使用了。

这会加速渲染,因为所有的Material 内容现在长久在GPU显存里。

专用的代码管理着每个大型的object GPU CBUFFER,给所有的objecct 属性。


SRP Batcher 兼容性

用SRP Batcher去渲染一个物体的条件如下:

1、渲染的物体必须是一个mesh或者skinned mesh。不能是粒子。

2、Shader代码必须兼容SRP Batcher。

3、该材质不能在运行中被代码修改MaterialPropertyBlock,否则也无法compatible SRP Batcher。(12月24号更新)


兼容SRP Batcher的Shader的条件如下:

1、必须声明所有内建引擎properties 在一个名为"UnityPerDraw"的CBUFFER里。

例如:URP内置的UnityInput.hlsl里。也就是说,如果你的代码有引用或间接引用UnityInput.hlsl,那就不用做这一步了。

​2、必须声明所有材质properties在一个名为"UnityPerMaterial"的CBUFFER里。

这个我上一篇文章有具体的实现步骤,这个是传送门:

在C#代码中,可以用以下代码在游戏运行时打开SRP Batcher.

GraphicsSettings.useScriptableRenderPipelineBatching = true;


支持的手机平台:

IOS Metal

OpenGL ES 3.1以上

Vulkan


以上,希望本文能给正在使用URP和HDRP的人提供一些帮助。

2021年1月更新:

unity2020.2的文档

docs.unity3d.com/2020.2

里面说的,HDRP是默认打开SRP Batcher的,如果想关掉它,要进入Debug Mode才行。

或者代码中写

GraphicsSettings.useScriptableRenderPipelineBatching = false;

当然我们一般都不会关。

本文参考文章:

docs.unity3d.com/Manual

编辑于 01-09 22:02

文章被以下专栏收录

9 条评论

  • 大超 2020-10-15

    为什么最终 Saved byBatching是个负数???

  • UoO-OoU11-11
    傻傻的问一句,内置管线里的cbuffer是啥来的[发呆]
  • 感谢大佬讲的很清楚,懂是懂了,这个手打牛肉丸是个什么梗[发呆]
  • 发现很多技术都是换汤不换药的。至少思想上是的。这种合并批次的类似VBO,和固定管线分布提交的早起模式。降低CPU和GPU上下文设备切换。提高CPU的吞吐量。

  • Jave回复泥潭里的金鱼2020-10-30
    大佬,不是VAO吗?(批量VBO设置了)
  • MaxwellGeng 2020-10-10
    建议自己用dx12/vk/metal按照原理实现一遍然后贴代码,不然只讲理论信服程度不够
  • 琅琅 (作者) 回复MaxwellGeng 2020-10-10
    目前只是按官方文档原文翻译而已哦。
  • Atlas2020-09-21

    官方文档上说不能是蒙皮网格

  • 琅琅 (作者) 回复Atlas2020-09-21

    可以的,官方原文是:

    SRP Batcher compatibility
    For the SRP Batcher code path to render an object:

    The rendered object must be a mesh
    or skinned mesh. It cannot be a particle.

    详见docs.unity3d.com/Manual

想来知乎工作?请发送邮件到 jobs@zhihu.com